package com.octopus.kernal.ui.element;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;

import com.octopus.kernal.model.BaseStruct;

@SuppressWarnings("serial")
@XmlType(name="CheckboxElement")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class CheckboxElement extends BaseElement{
	
	@XmlAttribute
	private Boolean list = false;
	
	@XmlAttribute
	private String type = "String";
	
	@XmlAttribute
	private String labelProperty;
	
	@XmlAttribute
	private Integer layout = 1;
	
	@XmlAttribute
	private String width = "100%";
	
	@XmlTransient
	private MessageSource messageSource;
	
	@XmlTransient
	private List<Object> entitiesScrope;
	
	@XmlTransient
	private String sp = System.getProperty("line.separator");
	
	@SuppressWarnings("unchecked")
	@Override
	public String toString(){
		StringBuffer str = new StringBuffer();
		if(list){
			Set<Object> entities = (Set<Object>)this.getValue();
			List<String> keys = new ArrayList<String>();
			if(entities != null){
				for(Object entity : entities){
					if(entity != null){
						keys.add(this.getEntityId(entity));
					}
				}
			}
			if(this.isReadonly()){
				if(entities == null)
					return "";
				for(Object entity : entities){
					if(entity == null)
						continue;
					str.append(this.getEntityLabel(entity));
					str.append(" , ");
				}
				if(str.lastIndexOf(" , ") != -1)
					str.delete(str.lastIndexOf(" , "), str.length());
			}else{
				if(entitiesScrope == null)
					return "";
				int index = 0;
				str.append("<table width=\"" + this.width + "\">" + sp);
				for(Object entity : entitiesScrope){
					if(index++ % layout == 0)
						str.append("<tr>" + sp);
					str.append("<td width=\"" + 100/layout + "%\">" + sp);
					str.append("<input type=\"checkbox\" ");
					if(this.getName() != null)
						str.append("name=\"" + this.getName() + "\" ");
					if(this.isDisabled())
						str.append("disabled=\"disabled\" ");
					if(this.getOnclick() != null)
						str.append("onclick=\"" + this.getOnclick() + "\" ");
					str.append("value=\"" + this.getEntityId(entity)  + "\" ");
					if(keys.contains(this.getEntityId(entity)))
						str.append("checked=\"checked\" ");
					if(this.getCssclass() != null)
						str.append("class=\"" + this.getCssclass().toString() + "\" ");
					if(this.getStyle() != null)
						str.append("style=\"" + this.getStyle().toString() + "\" ");
					str.append(">");
					str.append(this.getEntityLabel(entity));
					str.append("</td>" + sp);
					if(index % layout == 0)
						str.append("</tr>" + sp);
				}
				str.append("</table>" + sp);
			}
		}else{
			boolean value = null==this.getValue()?false:(Boolean)this.getValue();
			if(this.isReadonly()){
				String msg = messageSource.getMessage("label.common.no", new Object[] { }, LocaleContextHolder.getLocale());
				if(value)
					msg = messageSource.getMessage("label.common.yes", new Object[] { }, LocaleContextHolder.getLocale());
				str.append(msg);
			}else{
				str.append("<input type=\"checkbox\" ");
				if(this.getId() != null)
					str.append("id=\"" + this.getId() + "\" ");
				if(this.getName() != null)
					str.append("name=\"" + this.getName() + "\" ");
				if(this.isDisabled())
					str.append("disabled=\"disabled\" ");
				if(this.getOnclick() != null)
					str.append("onclick=\"" + this.getOnclick() + "\" ");
				if(this.getValue() != null)
					str.append("value=\"true\" ");
				if(value)
					str.append("checked=\"checked\" ");
				if(this.getCssclass() != null)
					str.append("class=\"" + this.getCssclass().toString() + "\" ");
				if(this.getStyle() != null)
					str.append("style=\"" + this.getStyle().toString() + "\" ");
				str.append(">");
			}
		}
		return str.toString();
	}
	
	private String getEntityId(Object entity){
		if(type.equals("String")){
			return String.valueOf(entity);
		}else if(type.equals("Integer")){
			return String.valueOf(entity);
		}else if(type.equals("Boolean")){
			return String.valueOf(entity);
		}else if(type.equals("Date") || type.equals("Time")){
			return String.valueOf(entity);
		}else{
			return String.valueOf(((BaseStruct)entity).getId());
		}
	}
	
	private String getEntityLabel(Object entity){
		String label = "";
		if(type.equals("String")){
			return String.valueOf(entity);
		}else if(type.equals("Integer")){
			return String.valueOf(entity);
		}else if(type.equals("Boolean")){
			return String.valueOf(entity);
		}else if(type.equals("Date") || type.equals("Time")){
			return String.valueOf(entity);
		}else{
			label = null==labelProperty?String.valueOf(((BaseStruct)entity).getId()):getTranslationValue(String.valueOf(((BaseStruct)entity).getAttributeValues().get(labelProperty)));
		}
		return label;
	}
	
	public String getName() {
		if(super.getName() == null)
			return null;
		else if(type.equals("String"))
			return super.getName();
		else if(type.equals("Integer"))
			return super.getName();
		else if(type.equals("Boolean"))
			return super.getName();
		else if(type.equals("Date") || type.equals("Time"))
			return super.getName();
		else if(super.getName().lastIndexOf("Id") == (super.getName().length() - 2))
			return super.getName();
		else
			return super.getName() + "Id";
	}
	
	public CheckboxElement clone(){
		CheckboxElement result = new CheckboxElement();
		try {
			BeanUtils.copyProperties(result, this);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public Boolean getList() {
		return list;
	}

	public void setList(Boolean list) {
		this.list = list;
	}

	public MessageSource getMessageSource() {
		return messageSource;
	}

	public void setMessageSource(MessageSource messageSource) {
		this.messageSource = messageSource;
	}

	public String getLabelProperty() {
		return labelProperty;
	}

	public void setLabelProperty(String labelProperty) {
		this.labelProperty = labelProperty;
	}

	public List<Object> getEntitiesScrope() {
		return entitiesScrope;
	}

	public void setEntitiesScrope(List<Object> entitiesScrope) {
		this.entitiesScrope = entitiesScrope;
	}

	public Integer getLayout() {
		return layout;
	}

	public void setLayout(Integer layout) {
		this.layout = layout;
	}

	public String getWidth() {
		return width;
	}

	public void setWidth(String width) {
		this.width = width;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
}
